package com.ingenieria.industrial.dao.implementacion;

import com.ingenieria.industrial.dao.diseño.IProcesoDAO;
import com.ingenieria.industrial.dto.Documento;
import com.ingenieria.industrial.dto.Formato;
import com.ingenieria.industrial.dto.Proceso;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.joda.time.DateTime;

public class ProcesoDAO extends BaseDAO implements IProcesoDAO {

    public ProcesoDAO(Connection cnx) {
        super(cnx);
    }

    @Override
    public int insert(Proceso proceso) throws SQLException {
        String max = null;
        int maximo = 0;
        String codigo = null;
        String sql0 = "select max(substring(cod_proc,3)) as maximo from t_procesos";
        PreparedStatement ps0 = cnx.prepareStatement(sql0);
        ResultSet rs0 = ps0.executeQuery();
        if (rs0.next()) {
            max = rs0.getString("maximo");
        }
        if (isVacio(max)) {
            max = "0";
        }
        maximo = toInt(max) + 1;
        codigo = "P" + rellenarCadIzquierda(convCadena(maximo), 3, '0');
        int results = -1;
        String sqlQuery = "INSERT INTO t_procesos(cod_proc, nombre, descrip, tip_proc, estado, usu_reg, fec_reg) "
                + " VALUES(?, ?, ?, ?, ?, ?, ?); ";
        PreparedStatement ps = cnx.prepareStatement(sqlQuery);
        int pos = 1;
        ps.setString(pos++, codigo);
        ps.setString(pos++, proceso.getNombre());
        ps.setString(pos++, proceso.getDescrip());
        ps.setString(pos++, proceso.getTip_proc());
        ps.setString(pos++, proceso.getEstado());
        ps.setString(pos++, proceso.getUsu_reg());
        ps.setTimestamp(pos++, toTimestampSQL(DateTime.now()));
        results = ps.executeUpdate();
        ps0.close();
        rs0.close();
        ps.close();

        if (proceso.getFileData().getSize() != 0) {
            //Guardando Documentos
            String sqlQuery2 = "INSERT INTO t_documentos( tip_doc, codigo, documento, usu_reg, fec_reg, nom_arch) "
                    + " VALUES(?, ?, ?, ?, ?, ?); ";
            PreparedStatement ps2 = cnx.prepareStatement(sqlQuery2);
            pos = 1;
            ps2.setString(pos++, "P");
            ps2.setString(pos++, codigo);
            try {
                ps2.setBinaryStream(pos++, proceso.getFileData().getInputStream(), proceso.getFileData().getFileItem().getSize());
            } catch (IOException ex) {
                Logger.getLogger(ProcesoDAO.class.getName()).log(Level.SEVERE, null, ex);
            }
            ps2.setString(pos++, proceso.getUsu_reg());
            ps2.setTimestamp(pos++, toTimestampSQL(DateTime.now()));
            ps2.setString(pos++, proceso.getFileData().getFileItem().getName());
            ps2.executeUpdate();
            ps2.close();
        }
        if (proceso.getFileDataFor().getSize() != 0) {
            //Guardando Formatos
            String maxF = null;
            int maximoF = 0;
            String codigoF = null;
            String sqlF = "select max(substring(cod_proc,3)) as maximo from t_formatos";
            PreparedStatement psF = cnx.prepareStatement(sqlF);
            ResultSet rsF = psF.executeQuery();
            if (rsF.next()) {
                maxF = rsF.getString("maximo");
            }
            if (isVacio(maxF)) {
                maxF = "0";
            }
            maximoF = toInt(maxF) + 1;
            codigoF = "F" + rellenarCadIzquierda(convCadena(maximoF), 3, '0');
            String sqlQuery3 = "INSERT INTO t_formatos(cod_for, nombre, descrip, cod_proc, usu_reg, fec_reg)"
                    + " VALUES(?, ?, ?, ?, ?, ?)";
            PreparedStatement ps3 = cnx.prepareStatement(sqlQuery3);
            int pos2 = 1;
            ps3.setString(pos2++, codigoF);
            ps3.setString(pos2++, proceso.getNombre_for());
            ps3.setString(pos2++, proceso.getDescrip_for());
            ps3.setString(pos2++, codigo);
            ps3.setString(pos2++, proceso.getUsu_reg());
            ps3.setTimestamp(pos2++, toTimestampSQL(DateTime.now()));
            ps3.executeUpdate();
            ps3.close();

            //Guardando Formatos en documentos
            String sqlQuery4 = "INSERT INTO t_documentos( tip_doc, codigo, documento, usu_reg, fec_reg, nom_arch) "
                    + " VALUES(?, ?, ?, ?, ?, ?)";
            PreparedStatement ps4 = cnx.prepareStatement(sqlQuery4);
            int pos1 = 1;
            ps4.setString(pos1++, "F");
            ps4.setString(pos1++, codigoF);
            try {
                ps4.setBinaryStream(pos1++, proceso.getFileDataFor().getInputStream(), proceso.getFileDataFor().getFileItem().getSize());
            } catch (IOException ex) {
                Logger.getLogger(ProcesoDAO.class.getName()).log(Level.SEVERE, null, ex);
            }
            ps4.setString(pos1++, proceso.getUsu_reg());
            ps4.setTimestamp(pos1++, toTimestampSQL(DateTime.now()));
            ps4.setString(pos1++, proceso.getFileDataFor().getFileItem().getName());
            ps4.executeUpdate();
            ps4.close();
        }
        return results;
    }

    @Override
    public int update(Proceso proceso) throws SQLException {
        int results = -1;
        String sqlQuery = "UPDATE t_procesos "
                + " SET nombre = ?, descrip = ?, tip_proc = ?,  estado = ? "
                + " WHERE cod_proc = ? ";
        PreparedStatement ps = cnx.prepareStatement(sqlQuery);
        int pos = 1;
        ps.setString(pos++, proceso.getNombre());
        ps.setString(pos++, proceso.getDescrip());
        ps.setString(pos++, proceso.getTip_proc());
        ps.setString(pos++, proceso.getEstado());
        ps.setString(pos++, proceso.getCod_proc());
        results = ps.executeUpdate();
        Documento documento = null;
        Formato formato = null;
        DocumentoDAO doc = new DocumentoDAO(cnx);
        FormatoDAO daoFor = new FormatoDAO(cnx);
        try {
            documento = doc.getByCodPro(proceso.getCod_proc());
            formato = daoFor.getByCodProc(proceso.getCod_proc());
        } catch (Exception ex) {
        }
        if (documento != null) {
            if (!isVacio(proceso.getFileData())) {
                String sqlQueryUpd = "UPDATE t_documentos SET"
                        + " tip_doc = ?, codigo = ?, documento =?, usu_reg = ?, fec_reg = ?, nom_arch = ? "
                        + " WHERE codigo = ?";
                PreparedStatement ps1 = cnx.prepareStatement(sqlQueryUpd);
                int pos1 = 1;
                ps1.setString(pos1++, "P");
                ps1.setString(pos1++, proceso.getCod_proc());
                try {
                    ps1.setBinaryStream(pos1++, proceso.getFileData().getInputStream(), proceso.getFileData().getFileItem().getSize());
                } catch (IOException ex) {
                    Logger.getLogger(ProcesoDAO.class.getName()).log(Level.SEVERE, null, ex);
                }
                ps1.setString(pos1++, proceso.getUsu_reg());
                ps1.setTimestamp(pos1++, toTimestampSQL(DateTime.now()));
                ps1.setString(pos1++, proceso.getFileData().getFileItem().getName());
                ps1.setString(pos1++, proceso.getCod_proc());
                ps1.executeUpdate();
                ps1.close();
            }
        } else {
            if (!isVacio(proceso.getFileData())) {
                String sqlQuery2 = "INSERT INTO t_documentos( tip_doc, codigo, documento, usu_reg, fec_reg, nom_arch) "
                        + " VALUES(?, ?, ?, ?, ?, ?); ";
                PreparedStatement ps2 = cnx.prepareStatement(sqlQuery2);
                pos = 1;
                ps2.setString(pos++, "P");
                ps2.setString(pos++, proceso.getCod_proc());
                try {
                    ps2.setBinaryStream(pos++, proceso.getFileData().getInputStream(), proceso.getFileData().getFileItem().getSize());
                } catch (IOException ex) {
                    Logger.getLogger(ProcesoDAO.class.getName()).log(Level.SEVERE, null, ex);
                }
                ps2.setString(pos++, proceso.getUsu_reg());
                ps2.setTimestamp(pos++, toTimestampSQL(DateTime.now()));
                ps2.setString(pos++, proceso.getFileData().getFileItem().getName());
                ps2.executeUpdate();
                ps2.close();
            }
        }
        if (formato != null) {
            String sqlQueryUpdFor = "UPDATE t_formatos SET "
                    + " nombre = ?, descrip = ?, fec_reg = ? "
                    + "WHERE cod_for = ? ";
            PreparedStatement ps3 = null;
            int pos3 = 1;
            ps3 = cnx.prepareStatement(sqlQueryUpdFor);
            ps3.setString(pos3++, proceso.getNombre_for());
            ps3.setString(pos3++, proceso.getDescrip_for());
            ps3.setTimestamp(pos3++, toTimestampSQL(DateTime.now()));
            ps3.setString(pos3++, proceso.getCod_for());
            ps3.executeUpdate();
            ps3.close();

            int pos2 = 1;
            PreparedStatement ps2 = null;
            if (!isVacio(proceso.getFileDataFor())) {
                String sqlQueryUpdForDoc = "UPDATE t_documentos SET"
                        + " tip_doc = ?, codigo = ?, documento =?, nom_arch = ?, usu_reg = ?, fec_reg = ? "
                        + " WHERE codigo = ?";
                ps2 = cnx.prepareStatement(sqlQueryUpdForDoc);
                ps2.setString(pos2++, "F");
                ps2.setString(pos2++, proceso.getCod_for());
                try {
                    ps2.setBinaryStream(pos2++, proceso.getFileDataFor().getInputStream(),
                            proceso.getFileDataFor().getFileItem().getSize());
                    ps2.setString(pos2++, proceso.getFileDataFor().getFileItem().getName());
                } catch (IOException ex) {
                    Logger.getLogger(ProcesoDAO.class.getName()).log(Level.SEVERE, null, ex);
                }
                ps2.setString(pos2++, proceso.getUsu_reg());
                ps2.setTimestamp(pos2++, toTimestampSQL(DateTime.now()));
                ps2.setString(pos2++, proceso.getCod_for());
                ps2.executeUpdate();
                ps2.close();
            } else {
                String sqlQueryUpdForDoc = "UPDATE t_documentos SET"
                        + " tip_doc = ?, codigo = ?, usu_reg = ?, fec_reg = ? "
                        + " WHERE codigo = ?";
                ps2 = cnx.prepareStatement(sqlQueryUpdForDoc);
                ps2.setString(pos2++, "F");
                ps2.setString(pos2++, proceso.getCod_for());
                ps2.setString(pos2++, proceso.getUsu_reg());
                ps2.setTimestamp(pos2++, toTimestampSQL(DateTime.now()));
                ps2.setString(pos2++, proceso.getCod_for());
                ps2.executeUpdate();
                ps2.close();
            }
        } else {
            if (!isVacio(proceso.getFileDataFor())) {
                //Guardando Formatos
                String maxF = null;
                int maximoF = 0;
                String codigoF = null;
                String sqlF = "select max(substring(cod_proc,3)) as maximo from t_formatos";
                PreparedStatement psF = cnx.prepareStatement(sqlF);
                ResultSet rsF = psF.executeQuery();
                if (rsF.next()) {
                    maxF = rsF.getString("maximo");
                }
                if (isVacio(maxF)) {
                    maxF = "0";
                }
                maximoF = toInt(maxF) + 1;
                codigoF = "F" + rellenarCadIzquierda(convCadena(maximoF), 3, '0');
                String sqlQuery3 = "INSERT INTO t_formatos(cod_for, nombre, descrip, cod_proc, usu_reg, fec_reg)"
                        + " VALUES(?, ?, ?, ?, ?, ?)";
                PreparedStatement ps3 = cnx.prepareStatement(sqlQuery3);
                int pos2 = 1;
                ps3.setString(pos2++, codigoF);
                ps3.setString(pos2++, proceso.getNombre_for());
                ps3.setString(pos2++, proceso.getDescrip_for());
                ps3.setString(pos2++, proceso.getCod_proc());
                ps3.setString(pos2++, proceso.getUsu_reg());
                ps3.setTimestamp(pos2++, toTimestampSQL(DateTime.now()));
                ps3.executeUpdate();
                ps3.close();

                //Guardando Formatos en documentos
                String sqlQuery4 = "INSERT INTO t_documentos( tip_doc, codigo, documento, usu_reg, fec_reg, nom_arch) "
                        + " VALUES(?, ?, ?, ?, ?, ?)";
                PreparedStatement ps4 = cnx.prepareStatement(sqlQuery4);
                int pos1 = 1;
                ps4.setString(pos1++, "F");
                ps4.setString(pos1++, codigoF);
                try {
                    ps4.setBinaryStream(pos1++, proceso.getFileDataFor().getInputStream(), proceso.getFileDataFor().getFileItem().getSize());
                } catch (IOException ex) {
                    Logger.getLogger(ProcesoDAO.class.getName()).log(Level.SEVERE, null, ex);
                }
                ps4.setString(pos1++, proceso.getUsu_reg());
                ps4.setTimestamp(pos1++, toTimestampSQL(DateTime.now()));
                ps4.setString(pos1++, proceso.getFileDataFor().getFileItem().getName());
                ps4.executeUpdate();
                ps4.close();
            }
        }

        ps.close();
        return results;
    }

    @Override
    public int delete(String cod_proc) throws SQLException {
        int results = -1;
        String sqlQuery = "DELETE FROM t_procesos WHERE cod_proc = ? ";
        PreparedStatement ps = cnx.prepareStatement(sqlQuery);
        ps.setString(1, cod_proc);
        results = ps.executeUpdate();
        ps.close();
        return results;
    }

    @Override
    public ArrayList<Proceso> getAll() throws SQLException {
        ArrayList<Proceso> lista = null;
        Proceso proceso = null;
        String sqlQuery = "SELECT p.* "
                + " FROM t_procesos p "
                + " ORDER BY p.cod_proc";
        PreparedStatement ps = cnx.prepareStatement(sqlQuery);
        ResultSet rs = ps.executeQuery();
        lista = new ArrayList<>();
        while (rs.next()) {
            proceso = new Proceso();
            mapearBeanForRS(rs, proceso);
            lista.add(proceso);
        }
        rs.close();
        ps.close();
        return lista;
    }

    @Override
    public Proceso getById(String cod_proc) throws SQLException {
        Proceso proceso = null;
        String sqlQuery = "SELECT p.*, (SELECT documento FROM t_documentos WHERE codigo = p.cod_proc) AS documento, "
                + " (SELECT nom_arch FROM t_documentos WHERE codigo = p.cod_proc) AS nom_arch, "
                + " (SELECT cod_for FROM t_formatos WHERE cod_proc =  p.cod_proc) AS cod_for, "
                + " (SELECT nombre FROM t_formatos WHERE cod_proc = p.cod_proc) AS nombre_for, "
                + " (SELECT descrip FROM t_formatos WHERE cod_proc = p.cod_proc) AS descrip_for, "
                + " (SELECT documento FROM t_documentos WHERE codigo = (SELECT cod_for FROM t_formatos WHERE cod_proc =  p.cod_proc)) AS documento_for, "
                + " (SELECT nom_arch FROM t_documentos WHERE codigo = (SELECT cod_for FROM t_formatos WHERE cod_proc= p.cod_proc)) AS nom_archFor"
                + " FROM t_procesos p "
                + " WHERE cod_proc = ? ";

        PreparedStatement ps = cnx.prepareStatement(sqlQuery);
        ps.setString(1, cod_proc);
        ResultSet rs = ps.executeQuery();
        while (rs.next()) {
            proceso = new Proceso();
            mapearBeanForRS(rs, proceso);
            Blob bytesImagen = rs.getBlob("documento");
            Blob byteImagenFor = rs.getBlob("documento_for");
            if (bytesImagen != null) {
                InputStream is = bytesImagen.getBinaryStream();
                proceso.setArchivo(is);
            }
            if (byteImagenFor != null) {
                InputStream is = byteImagenFor.getBinaryStream();
                proceso.setArchivoFor(is);
            }
        }
        rs.close();
        ps.close();
        return proceso;
    }

    @Override
    public ArrayList<Proceso> getListxTipo(String tipo) throws SQLException {
        ArrayList<Proceso> lista = null;
        Proceso proceso = null;
//        String sqlQuery = "SELECT p.* "
//                + " FROM t_procesos p "
//                + " WHERE tip_proc = ? "
//                + " ORDER BY p.cod_proc";
        String sqlQuery = " select p.*, (select documento from t_documentos where codigo = p.cod_proc) as documento, "
                + " (select nom_arch from t_documentos where codigo = p.cod_proc) as nom_arch "
                + " FROM t_procesos p "
                + " WHERE tip_proc = ?";
        PreparedStatement ps = cnx.prepareStatement(sqlQuery);
        ps.setString(1, tipo);
        ResultSet rs = ps.executeQuery();
        lista = new ArrayList<>();
        while (rs.next()) {
            proceso = new Proceso();
            mapearBeanForRS(rs, proceso);
            lista.add(proceso);
        }
        rs.close();
        ps.close();
        return lista;
    }

}
